Manipulate Secrets Revealed

Mathematica 10

Lou D’Andria

Wolfram Research, Inc.

The ubiquitous Manipulate function will be used in many talks at this conference, and is the basis for such ventures as the Demonstrations Project and Wolfram CDF Player. But just how well do you know the Manipulate function? In this talk, we will examine some of its lesser known features, ranging from those that are fully documented to those that are not documented at all. The goal of this talk is to empower you to become a Manipulate expert.

Topics

New in 10: TrackingFunction, IntervalSlider, …

Synchronicity: crafting responsive interfaces

New in 10: TrackingFunction

It has always been possible to create a control which did more that simply set a variable, via the second argument to Dynamic.

Slider[Dynamic[x,(x=#; y=1-#)&],{0,1}]
Dynamic[{x,y}]

Now, there’s an option to do this easily in Manipulate too: TrackingFunction

Simple example

Manipulate[{x,y},{x,0,1,TrackingFunction->((x=#;y=(1-#))&)},{y,0,1}]

LocatorPane -- restrict a single locator

Manipulate[Graphics[Circle[],PlotRange ->2],{{pt,{0,0}},Locator,TrackingFunction->(pt=#/Max[Norm[#],1];&)}]

LocatorPane -- restrict multiple locators

The accessor CurrentValue[“CurrentLocatorPaneThumb”] is very useful for this.

Manipulate[Graphics[{Line[{{-2,-2},{2,2}}],Circle[]},PlotRange ->2],{{pts,{{1,1},{-0.5,0}}},Locator,TrackingFunction->(Switch[CurrentValue["CurrentLocatorPaneThumb"],
1,pts[[1]]=#[[1,{1,1}]],
2,pts[[2]]=#[[2]]/Max[Norm[#[[2]]],1]];&)}]

Bonus

In fact, CurrentValue[“CurrentLocatorPaneThumb”] is critical to the implementation of IntervalSlider.

New in 10.0.1: UndoTrackedVariables

The single best new feature in 10: Multiple Undo.

How does this interact with Dynamic / DynamicModule / Manipulate?

Example

Button["Edit > Undo", FrontEndTokenExecute["Undo"]]

Manipulate[{x,y},{x,0,1},{y,0,1},UndoTrackedVariables:>{x}]

New in 10: IntervalSlider

There is now a control which lets you select an interval.

IntervalSlider[Dynamic[int],{0,1}]
Dynamic[int]

IntervalSlider options

Labeled[IntervalSlider[Method -> #],#]& /@ {"Free","Push","Stop"}

IntervalSlider[MinIntervalSize -> 0.1]

IntervalSlider in Manipulate

IntervalSlider can be used in Manipulate via the ControlType option.

Manipulate[int,{int,0,1,ControlType -> IntervalSlider}]

Example

Lots of functions and options take a {min, max} setting.

Manipulate[Plot3D[x Exp[-x^2-y^2],{x,-2,2},{y,-2,2},PlotRange->zrange,ClippingStyle->None],{zrange,-1,1,ControlType -> IntervalSlider}]

Example

Of course, Manipulate controls can refer to other Manipulate controls.

Manipulate[x,{int,0,1,ControlType -> IntervalSlider,Appearance -> "Labeled"},{{x,0.5},int[[1]], int[[2]]}]

Bonus

Visualizing the Cantor set construction.

cantorInterval[n_Integer?NonNegative, {min_, max_}]:=
Interval@@Nest[Flatten[Replace[#,{a_,b_}:>{{a,a+(b-a)*min},{a+(b-a)*max,b}},{1}],1]&,{{0,1}},n]

showCantorIntervals[n_Integer?NonNegative, {min_, max_}]:=NumberLinePlot[Table[cantorInterval[i,{min,max}],{i,0,n}],PlotRange -> {{0,1},Automatic},ImageSize -> 600,PlotRangePadding -> 0.05]

Manipulate[showCantorIntervals[n,int],{int,0,1,ControlType -> IntervalSlider},{int},{n,1,5,1}]

Bonus

There’s also a stepper control.

DynamicModule[{int={.3,.7}},{IntervalSlider[Dynamic[int],{0,1}],Experimental`IntervalStepper[Dynamic[int],{0,1,0.1}],Dynamic[int]}]

And a general multi-valued slider control.

DynamicModule[{vals=Sort @ RandomSample[Range[10],4]},{Experimental`MultiSlider[Dynamic[vals],{0,10,1}],Dynamic[vals]}]

New in 10: An option walks into a bar…

The “Bar” family of controls (SetterBar, RadioButtonBar, TogglerBar, CheckboxBar, ButtonBar) have always supported a small number of Appearance settings: “Row”, “Vertical”, “Horizontal”.

Manipulate[country,{country,CountryData["SouthAmerica"],SetterBar}]

Manipulate[country,{country,CountryData["SouthAmerica"],SetterBar,Appearance -> "Row"}]

New Appearance settings

Appearance -> "Vertical" -> {h, w}
Appearance -> “Horizontal” -> {h, w}

Manipulate[country,{country,CountryData["SouthAmerica"],SetterBar,Appearance -> "Vertical"->{Automatic,3}}]

Of course, these are support outside of Manipulate too.

New Method settings

CheckboxBar and RadioButtonBar and OpenerView support Method -> “Active” to make the labels clickable, off by default.

Manipulate[country,{country,CountryData["SouthAmerica"],RadioButtonBar,Appearance -> "Vertical"->{Automatic,3},Method -> "Active"}]

See also

Multicolumn -- a utility for creating grids automatically from a flat list of elements.

Multicolumn[CountryData["SouthAmerica"],{Automatic,3}]

Bonus

Bonus

Over the years, there has been quite a bit of confusion about when to use Module and when to use DynamicModule.

We've added some syntax coloring to discourage inappropriate use of Module with Manipulate and related constructs.

Module[{x},Manipulate[{x,y},{y,0,1}]]

For an in depth discussion about this issue, see the Advanced Dynamic Functionality tutorial here.

Synchronicity

Manipulate should always be responsive, but some evaluations just take time.

Manipulate[(Pause[10];x),{x,0,1}]

Manipulate[x,{x,0,1},Initialization:>(Pause[10];x=1)]

Manipulate[x,{x,0,Pause[10];1}]

Manipulate[x,{x,0,1,Dynamic[Pause[10];Slider[##]]&}]

What’s the right way to handle evaluations that take longer than a seconds?

Synchronicity options

There are two evaluation modes for dynamic content: synchronous and asynchronous.

Manipulate[Zeta[x],{x,0,1}]

c=0;While[True,Pause[2];Print[++c]]

“Synchronous” vs “Asynchronous”

“Synchronous”
• preemptive
• very responsive
• no indication on the cell bracket
• can handle short evaluations
• effectively pauses the front end while waiting
• times out after a few seconds

“Asynchronous”
• queued
• same queue as shift-return
• can handle long running evaluations
• cell bracket highlights until evaluation is complete
• can be preempted
• doesn’t interfere with other front end interactions

Dynamic option: SynchronousUpdating

The default for Dynamic is SynchronousUpdating -> True, which is perfect for short evaluations, but can cause trouble for longer ones.

Dynamic[Pause[10];2+2]

Dynamic[Pause[10];2+2,SynchronousUpdating->False]

DynamicModule option: SynchronousInitialization

The default for DynamicModule is SynchronousInitialization -> True, which again can cause problems for longer running initializations.

DynamicModule[{x=0},Dynamic[x],Initialization:>(Pause[10];x=1)]

DynamicModule[{x=0},Dynamic[x],Initialization:>(Pause[10];x=1),SynchronousInitialization -> False]

Button option: Method

Button and ActionMenu take a Method option for determining whether to evaluate synchronously (Method -> “Preemptive”) or asynchronously (Method -> “Queued”).

Like Dynamic and DynamicModule, these options are set to synchronous mode by default.

Dynamic[x]

Button["click",Pause[2];x=π,Method -> "Queued"]

ActionMenu["click",MapThread[#1:>(Pause[#2];x=#2)&,{{"one","two","three"},{1,2,3}}],Method -> "Queued"]

FileNameSetter

There’s not even a Method option here, because the button should always use Method -> “Queued”.

FileNameSetter[Dynamic[file]]

Bonus

Note that depending on the values of these options, a DynamicModule’s initialization might evaluate after some Dynamics that are inside the DynamicModule.

list={};
DynamicModule[{x=(AppendTo[list,"var init"];0)},Dynamic[AppendTo[list,"dynamic display"];Pause[1];x, TrackedSymbols:>{x},SynchronousUpdating->True],Initialization:>(AppendTo[list,"init"];Pause[2];x=1),SynchronousInitialization->False]

list

This is actually a fairly common idiom for showing progress during long running evaluations.

DynamicModule[{x=0,update},Dynamic[If[x<100,ProgressIndicator[x,{0,100}],{x,Button["again",update[],Method -> "Queued"]}], SynchronousUpdating->True],Initialization:>(update[]:=Do[Pause[.01];x=i,{i,100}]; update[]),SynchronousInitialization->False]

Synchronicity options in Manipulate

Style[Grid[{
{Style["Manipulate options",Italic],Style["Short evaluation",Bold],Style["Long evaluation",Bold]},
{Style[SynchronousUpdating -> True,Bold],"perfect","might time out, $Aborted"},
{Style[SynchronousUpdating -> False,Bold],"excess overhead, waits in queue","perfect"},
{Style[SynchronousUpdating -> Automatic ,Bold],"sync","async"},
{Style[SynchronousInitialization -> True,Bold],"perfect","might time out, silently"},
{Style[SynchronousInitialization -> False,Bold],"excess overhead, waits in queue","perfect"}
},
Alignment -> {Center,Center},
Background-> {"Rows" -> {{White,GrayLevel[0.9]}}},
Dividers->{Center,{False,True,False,False,True,False,True}},
FrameStyle -> GrayLevel[0.5],
ItemSize -> {"Columns" -> {{Scaled[0.3]}}},
Spacings -> {1,1.5}],
"Text", 
TextAlignment -> Center]

SynchronousInitialization

If you have a one-time evaluation that might take longer than a few seconds, put it in the Initialization option, and set SynchronousInitilization to False.

Manipulate[x,{x,0,1},Initialization:>(Pause[10];x=1),SynchronousInitialization->False]

SynchronousUpdating

Manipulate’s first argument gets wrapped in Dynamic. That Dynamic has SynchronousUpdating -> Automatic by default.

If evaluating the first argument might take longer than that during interactive manipulation, set SynchronousUpdating -> False and possibly ContinuousAction -> False. (You should also think hard about whether such an example belongs in Manipulate to begin with.

Manipulate[(Pause[2];x),{x,0,1,ContinuousAction -> False}, SynchronousUpdating->False]

ControlActive

Another possibility is to use ControlActive. Note that ControlActive works best with the default SynchronousUpdating setting, Automatic, which switches between True and False as needed.

Manipulate[ControlActive[Row[{hz," Hz"}],Play[Sin[hz 2 Pi t],{t,0,1}]],{hz,220,880}]

ControlActive is the basis for PerformanceGoal.

Manipulate[Plot3D[Sin[n x y],{x,0,3},{y,0,3}],{{n,4},1,5}]

Note that the default SynchronousUpdating -> Automatic allows even the initial display to be shown first in preview mode, and then in full mode.

Bonus

Incremental display of graphics in a Manipulate. Note the use of ControlActive, and an inner DynamicModule which sets SynchronousInitialization -> False.

Manipulate[ControlActive[Graphics[{LightRed,Circle[{0,0},r]},PlotRange->{{-1,1},{-1,1}}],DynamicModule[{exprs={Red,Circle[{0,0},r]},rr=r},Graphics[Dynamic[exprs],PlotRange->{{-1,1},{-1,1}}],Initialization:>(If[rr=!=r,Abort[]];Pause[1];AppendTo[exprs,{Red,Disk[{0,0},rr]}];If[rr=!=r,Abort[]];Pause[1];AppendTo[exprs,{Black,Circle[{0,0},rr]}]),SynchronousInitialization->False]],{{r,0.5},0,1}]

Synchronicity rule of thumb

Any evaluation which requires the network or cloud, or asks the user anything should be asynchronous, or queued, to account for delays that will inevitably occur. Otherwise, you risk a timeout.

Manipulate[GeoGraphics[GeoMarker[],GeoRange->Quantity[n,"Miles"]],{n,0.1,100},SynchronousUpdating->False]

Questions?